﻿//////////////////////////////////////////////////////////////////
//
// Charles\Program.cs
//
// Copyright (c) 2012 Dan Pike.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Interfaces;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
using Utilities;

namespace Charles
{
   static class Program
   {
      public static Form MainForm;
      public static Logger Logger;
      public static Factory.Loader Loader;
      public static Configuration AppConfig;
      public static Config.Charles Settings;
      public static Interfaces.IAlmanac Almanac;
      public static string senderId = Identifiers.Charles;
      public static EventWaitHandle ProgramRunning;

      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main()
      {
         bool createdNew = false;
         try
         {
            // Prevent duplication
            using (ProgramRunning = new EventWaitHandle(false, EventResetMode.ManualReset, senderId, out createdNew))
            {
               if (!createdNew)
               {
                  MessageBox.Show(string.Concat(Application.ProductName, " is already running, this will now close"),
                     Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Stop);
                  return;
               }

               // Create the main form but don't display it, yet
               Application.EnableVisualStyles();
               Application.SetCompatibleTextRenderingDefault(false);
               MainForm = new Main();

               // Defer to the Network class to start everything up in the correct order (OAOO!)
               if (Network.Program.Initialize<Config.Charles>(MainForm, Config.Charles.CONFIG_SECTION, out Settings))
               {
                  // Plug into the global settings that we just created
                  Logger = Network.Program.Logger;
                  Loader = Network.Program.Loader;
                  AppConfig = Network.Program.AppConfig;
                  Almanac = Network.Program.Almanac;

                  // Start up the GUI
                  Application.Run(MainForm);

                  // Shut down everything neatly
                  Network.Program.shutdown();
               }
            }
         }
         catch (Exception ex)
         {
            // We didn't catch the exception
            if (null != Logger)
            {
               // Yippee! The logger exists, so we can dump the call stack
               Logger.Exception(ex);
            }

            MessageBox.Show(
               string.Concat(Application.ProductName, " threw an exception: ", ex.Message),
               Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Stop);
         }
         finally
         {
            if (null != Logger)
            {
               Logger.DebugFormat("{0} is exiting", Application.ProductName);
            }
         }
      }
   }
}
